-
Notifications
You must be signed in to change notification settings - Fork 5
feat: add createProperty, createType, createEntity #31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
🦋 Changeset detectedLatest commit: 3996cb5 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
5d937d1 to
06d1784
Compare
index.ts
Outdated
| * | ||
| * @since 0.5.0 | ||
| */ | ||
| export * as Graph from './src/graph/index.js'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm yeah not sure what we call this namespace. Graph seems fine I suppose.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, no better idea here so far
src/graph/create-entity.ts
Outdated
| let attributeValueType: 'TEXT' | 'CHECKBOX' | 'NUMBER' | 'URL' | 'POINT'; | ||
| switch (typeof value) { | ||
| case 'string': | ||
| attributeValueType = 'TEXT'; | ||
| break; | ||
| case 'boolean': | ||
| attributeValueType = 'CHECKBOX'; | ||
| break; | ||
| case 'number': | ||
| attributeValueType = 'NUMBER'; | ||
| break; | ||
| default: | ||
| throw new Error('Not implemented value type'); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So a couple points
- We probably want to make sure we support creating relations before we introduce something like this since creating relations is very common
- I think we should use the attribute id's value type as the source of truth for creating an entity rather than the JS value's primitive type. This would require fetching the data for each attribute and comparing it. But then we need to think about spaces and this starts to get more complex and verge into hypergraph territory. What if the value they use is different than the attribute's value type? Developers should be able to publish whatever triples they want even if it's against the schema. WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- makes sense @ relations, will add them
- how about a different mapping param e.g.
{
"name": {
id: "LuBWqZAu6pz54eiJS5mLv8",
valueType: "TEXT"
},
age: {
id: "someOtherId",
valueType: "NUMBER"
}
}But then should be decode the input an validate it matches the valueType? Feel odd if we allow to set the value type to number and then it would accept a string.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I think this is where it's tricky since the op itself should be the source of truth for what the value type is, and I don't think at this low level we want to force validation or anything since developers should be able to write whatever they want to the KG.
If we wanted to enforce validation then it should be a higher-level abstraction that lives in a higher-level package like hypergraph.
fe8cc18 to
bb35e3c
Compare
src/graph/create-relation-type.ts
Outdated
| name: string; | ||
| }; | ||
|
|
||
| export const createRelationType = async ({ from, to, name }: Params) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@baiirun the from and to are basically unused atm. I don't know if we even need them or and what triples should be set.
If I look at this type it doesn't seem to define from and to https://www.geobrowser.io/space/25omwWh6HYgeRQKCaSpVpa/U1uCAzXsRSTP4vFwo1JwJG
Only at the actual relation they seem to be defined: https://www.geobrowser.io/space/6tfhqywXtteatMeGUtd5EB/VbYuNDM2S9LKyij73Aj5CA
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is createRelationType meant to do?
yanivtal
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some feedback on the API
src/graph/graph.test.ts
Outdated
|
|
||
| describe('Graph', () => { | ||
| it('creates multiple types, relation types, entities, relations', async () => { | ||
| const operations: Array<Op> = []; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like we've standardized on the word ops, so it probably makes sense to stick to that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will change it to ops. Personally I don't like the naming op since I think it's a not obvious abbreviation to operation.
src/graph/graph.test.ts
Outdated
| const { | ||
| id: personTypeId, | ||
| ops: createPersonTypeOps, | ||
| mapping: personMapping, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Feels very heavy weight to pass this mapping around.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will create other proposals. I tried this approach since having one big mapping file will cause other developer experience issues.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would be an alternative version where you have function factory. Personally I would love something simpler. If you like it we can go with this one now. Since I learn more and more about GRC-20 specifics every day an alternative design might come out of this.
// initially defined mapping for an event
const mapping = {
event: {
types: ['AaGd6UMXfNtL6U6Xx7K8Cv'], // Event type
attributes: {
name: {
id: NAME_ATTRIBUTE,
type: 'TEXT',
},
},
relations: {
attendees: {
relationTypeId: 'AaGd6UMXfNtL6U6Xx7K8Cv',
},
},
},
};
// create a new attribute age
const { ops, id: ageAttributeId } = createAttributeEntity({
type: 'NUMBER',
name: 'Age',
});
// create a new attribute metFirst
const { ops, id: metFirstAttributeId } = createAttributeEntity({
type: 'TIME',
name: 'Met First',
});
// create a new type person
const { ops, mapping: personMapping } = createType({
attributes: {
name: {
id: NAME_ATTRIBUTE,
type: 'TEXT',
},
age: {
id: ageAttributeId,
type: 'NUMBER',
},
},
relations: {
friend: {
relationTypeId: 'AaGd6UMXfNtL6U6Xx7K8Cv',
attributes: {
metFirst: {
id: metFirstAttributeId,
type: 'TIME',
},
},
},
},
});
// add the new type to the mapping under the property person
mapping.person = personMapping;
// create the createEntity function
const createEntity = createEntityFactory(mapping);
// create an entity
const { ops: personOps, mapping: personMapping } = createEntity({
mappingKey: 'person',
attributes: {
name: 'John Doe',
},
relations: {
friend: [
{
id: 'ABCD', // other person ID
attributes: {
metFirst: 'Jane Doe',
},
},
],
},
});There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if we're over complicating things. Do we need the mappings? We could keep the API pretty close to the metal, just to create some convenience. What if it was just:
const { id: ID, ops: personOps } = createEntity({
triples: {
[NAME_PROPERTY]: {
value: 'John Doe',
type: TEXT,
},
},
relations: [
{
type: TYPES_PROPERTY,
to: PERSON_TYPE,
},
{
type: WORKS_AT_PROPERTY,
to: companyId,
triples: {
[START_TIME_PROPERTY]: {
value: startTime,
type: TIME,
format: 'MMMM do, yyyy'
},
}
]
})We could fold the types into the createEntity API but I'm not sure how much value it adds. The fact is this GRC-20 lib is still meant to be a fairly low level API. We want to have conveniences so people aren't dealing with encoding, decoding, etc. But I actually think it's fine for this API to expose the nuances of GRC-20. I don't think the goal should be that people don't need to understand the GRC-20 specifics. I think it's just to make working with it more ergonomic. I think this achieves that. Not perfectly ergonomic but not bad - and not adding magic and indirection.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I nice thing about using arrays for relations is that in shows that these are ordered. We should generate indexes for the relations. Triples aren't ordered, so it makes sense to have that in an object.
One potential issue to solve is right now we don't have a way to get the created relation IDs back from the function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
createRelation(
{
type: WORKS_AT_PROPERTY,
from: personId,
to: companyId,
triples: {
[START_TIME_PROPERTY]: {
value: startTime,
type: TIME,
}
}
)This would add Types: Relation and then set the given type here to the relationType.
src/graph/graph.test.ts
Outdated
| ops: createRestaurantTypeOps, | ||
| mapping: restaurantMapping, | ||
| } = await createType({ | ||
| attributes: { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we show an example of creating a Type that has attributes and relations?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
totally, didn't get to it yesterday
src/graph/graph.test.ts
Outdated
| operations.push(...createRestaurantTypeOps); | ||
|
|
||
| // create loves relation type | ||
| const { id: relationTypeId, ops: createRelationTypeOps } = await createRelationType({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is what a relation type is. It looks like this is mixing relations and relation types.
A relation type is something like "Works at". It's really just a Type and a Property, as we're currently using it. I think I need to update the spec to reflect this. "Relation type" should really just be a property, and not actually a type.
A relation is a thing that has a from and a to. So the fact that someone love's a restaurant is a relation. That relation would have "relation type": [Loves type/property ID].
There still is an open question on if we like this Type/Property duality or if we should go back to making something like "Loves" a separate thing, which could be called a relation type. But regardless, that doesn't seem to be what you're trying to create here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah totally, had the same question and did a call with Byron yesterday night and he clarified how it works
src/graph/graph.test.ts
Outdated
| attributes: { | ||
| name: 'Yummy Dining', | ||
| }, | ||
| mapping: restaurantMapping, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should find a way to not have to pass a mapping into every createEntity function call.
src/graph/graph.test.ts
Outdated
| name: 'John Doe', | ||
| }, | ||
| mapping: personMapping, | ||
| relations: [{ relationTypeId, toId: restaurantId }], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure about having Id on the keys here. Would think that relations should each look like:
{
relationType,
to,
attributes,
relations,
}
May want to show what this looks like with more than one relation (should have separate key, vals). I assume that the from is implied here as being the entity we're creating. Think it's worth making sure we can support adding additional properties to the relations.
ab89dcc to
20ecb70
Compare
…nstants with ATTRIBUTE still exist and marked as deprecated
20ecb70 to
36a28d9
Compare
| const relationOp = Relation.make({ | ||
| fromId: entityId, | ||
| relationTypeId: COVER_PROPERTY, | ||
| toId: cover, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The cover is actually an entity id and not just a string. Not sure the best API for users creating images yet. We do have an Image.make(...) function but it requires that they've uploaded their image to IPFS already and have a URL for it.
We might need to add an Ipfs.uploadImage function. The flow then might look like this.
const cid = await Ipfs.uploadImage(imageBinary);
const { imageId, imageOps } = Image.make(cid)Alternatively we can wrap the IPFS uploading part within Image.make
const { imageId, imageOps } = await Image.make(imageBinary)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As mentioned here #31 (comment) all IDs at the moment are strings. Is this fine or what should I change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Responded in this comment thread #31 (comment)
baiirun
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🚀
Added createProperty, createType, createEntity
publish and createSpace are also in there, publish needs more work and therefor I haven't documented it yet